package net.droiding.app;

import net.droiding.R;
import net.droiding.data.DroidingDao;
import net.droiding.data.DroidingParser;
import net.droiding.data.Provider;
import net.droiding.data.Station;
import net.droiding.net.DroidingConnection;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

public class Droiding {

	
	private static Droiding _instance = null;
	private Context ctx = null;
	
	
	private String username = null;
	private String passwd = null;
	private Provider provider = null;
	private Station[] stations = null;
	
	private DroidingDao dao = null;
	private DroidingConnection conn = null;
	
	
	private Droiding(Context ctx) {
		this.ctx = ctx;
		this.dao = new DroidingDao(this.ctx);
		loadPreferences();
	}
	public static Droiding getInstance(Context ctx) {
		if (_instance == null) {
			_instance = new Droiding(ctx);
		}
		return _instance;
	}
    private void savePreverences() {
		SharedPreferences settings = ctx.getSharedPreferences(ctx.getString(R.string.app_pref_filename), 0);
		SharedPreferences.Editor editor = settings.edit();
		if (username != null)
			editor.putString(ctx.getString(R.string.app_pref_key_user), username);
		if (passwd != null)
			editor.putString(ctx.getString(R.string.app_pref_key_pwd), passwd);
		if (provider != null)
	    editor.putString(ctx.getString(R.string.app_pref_key_provider), provider.key);
	    editor.commit();
	}
	private void loadPreferences() {
        SharedPreferences settings = ctx.getSharedPreferences(ctx.getString(R.string.app_pref_filename), 0);
        username = settings.getString(ctx.getString(R.string.app_pref_key_user), null);
        passwd = settings.getString(ctx.getString(R.string.app_pref_key_pwd), null);
        String pkey = settings.getString(ctx.getString(R.string.app_pref_key_provider), null);
        if (provider != null) {
    		this.provider = dao.getProvider(pkey);
    		this.stations = dao.getStations(pkey);
        }
    }
	public boolean hasUserAccount() {
		return (username != null && passwd != null);
	}	
	public void setUserAccount(String username, String passwd, Handler hnd) {
		this.username = username;
		this.passwd = passwd;
		savePreverences();
		LoginThread thread = new LoginThread(username, passwd, hnd);
		thread.start();
	}
	
	public boolean hasDefaultProvider() {
		return provider != null;
	}
	public boolean hasStations() {
		return (stations != null && stations.length > 0);
	}
	public DroidingDao getDao() {
		return dao;
	}
	public Provider getDefaultProvider() {
		return provider;
	}
	public void changeProvider(String pkey, Handler hnd) {
		ProviderChanger changer = new ProviderChanger(pkey, hnd);
		changer.start();
	}
	
	
	
//	public DroidingConnection getConnection() {
//		if (conn == null && hasUserAccount()) {
//			conn = new DroidingConnection(username, passwd);
//		}
//		return conn;
//	}
	public Station[] getStations() {
		return stations;
	}
//	public void updateStations(Station[] stations) {
//		for (Station st : stations) {
//			if (dao.getStationByRemoteId(st.remoteId) == null)
//				dao.insertStation(st);
//			else
//				dao.updateStation(st);
//		}
//		this.stations = stations;
//	}
	public void downloadProviders(Handler hnd) {
		ProviderDownloader downloader = new ProviderDownloader(this.username, this.passwd, hnd);
		downloader.start();
	}
	public void downloadStations(Handler hnd) {
		StationsDownloader downloader = new StationsDownloader(this.username, this.passwd, this.provider.key, hnd);
		downloader.start();
	}
	public void setStations(Station[] stations) {
		this.stations = stations;
	}

	private class ProviderChanger extends Thread {
		private Handler handler = null;
		private String pkey = null;
		ProviderChanger(String pkey, Handler handler) {
			this.pkey = pkey;
			this.handler = handler;
		}

		public void run() {
			try {
				provider = dao.getProvider(pkey);
				stations = dao.getStations(pkey);
				savePreverences();
				Message msg = handler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("result", "ok");
				msg.setData(b);
				handler.sendMessage(msg);
				return;
			} catch (Exception e) {
				Message msg = handler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("result", "ko");
				b.putString("error", e.getMessage());
				msg.setData(b);
				handler.sendMessage(msg);
			} 
		}
	}		
	
	private class LoginThread extends Thread {
		private Handler handler = null;
		private String username = null;
		private String passwd = null;

		LoginThread(String username, String passwd, Handler handler) {
			this.username = username;
			this.passwd = passwd;
			this.handler = handler;
		}

		public void run() {
			try {
				byte[] xml = DroidingConnection.login(username, passwd);
				if (DroidingParser.parseLogin(xml) != null) {
					Message msg = handler.obtainMessage();
					Bundle b = new Bundle();
					b.putString("result", "ok");
					msg.setData(b);
					handler.sendMessage(msg);
					return;
				}
				Message msg = handler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("result", "ko");
				b.putString("error", "null response");
				msg.setData(b);
				handler.sendMessage(msg);
			} catch (Exception e) {
				Message msg = handler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("result", "ko");
				b.putString("error", e.getMessage());
				msg.setData(b);
				handler.sendMessage(msg);
			} 
		}
	}	
	private class ProviderDownloader extends Thread {
		private Handler handler = null;
		private String username = null;
		private String passwd = null;

		ProviderDownloader(String username, String passwd, Handler handler) {
			this.username = username;
			this.passwd = passwd;
			this.handler = handler;
		}

		public void run() {
			try {
				byte[] xml = DroidingConnection.getAllProviders(username, passwd);
				Provider[] providers = DroidingParser.parseProviders(xml);
				if (providers != null) {
					getDao().insertProviders(providers);
					Message msg = handler.obtainMessage();
					Bundle b = new Bundle();
					b.putString("result", "ok");
					msg.setData(b);
					handler.sendMessage(msg);
					return;
				}
				Message msg = handler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("result", "ko");
				b.putString("error", "null response");
				msg.setData(b);
				handler.sendMessage(msg);
			} catch (Exception e) {
				Message msg = handler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("result", "ko");
				b.putString("error", e.getMessage());
				msg.setData(b);
				handler.sendMessage(msg);
			} 
		}
	}		
	private class StationsDownloader extends Thread {
		private Handler handler = null;
		private String username = null;
		private String passwd = null;
		private String pkey = null;

		StationsDownloader(String username, String passwd, String pkey, Handler handler) {
			this.username = username;
			this.passwd = passwd;
			this.pkey = pkey;
			this.handler = handler;
		}

		public void run() {
			try {
				byte[] xml = DroidingConnection.getStationsByProvider(username, passwd, pkey);
				Station[] sts = DroidingParser.parseStations(xml);
				if (sts != null) {
					for (Station st : sts) {
						if (dao.getStationByRemoteId(st.remoteId) == null)
							dao.insertStation(st);
						else
							dao.updateStation(st);
					}
					stations = sts;
					Message msg = handler.obtainMessage();
					Bundle b = new Bundle();
					b.putString("result", "ok");
					msg.setData(b);
					handler.sendMessage(msg);
					return;
				}
				Message msg = handler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("result", "ko");
				b.putString("error", "null response");
				msg.setData(b);
				handler.sendMessage(msg);
			} catch (Exception e) {
				Message msg = handler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("result", "ko");
				b.putString("error", e.getMessage());
				msg.setData(b);
				handler.sendMessage(msg);
			} 
		}
	}			
}
